﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using Clarke.Entities;

namespace Clarke.UI.Helpers
{
	public class SecurityHelper
	{
		public static bool IsLoggedIn
		{
			get
			{
				return HttpContext.Current.User.Identity.IsAuthenticated;
			}
		}

		public static string LoggedInUser
		{
			get
			{
				return HttpContext.Current.User.Identity.Name;
			}
		}

		public static void Login(string email, bool rememberMe)
		{
			var profile = ProfileCommon.GetProfile(email);
			profile.Save();

			FormsAuthentication.SetAuthCookie(email, rememberMe);
		}

		public static void Logout()
		{
			FormsAuthentication.SignOut();
		}

		public static bool ValidateUser(string email, string password)
		{
			return Membership.ValidateUser(email, password);
		}

		public static bool IsUserInRole(string role)
		{
			return Roles.IsUserInRole(role);
		}

		public static bool IsUserInRole(string email, string role)
		{
			return Roles.IsUserInRole(email, role);
		}

		public static bool UserExist(string email)
		{
			return Membership.GetUser(email) != null;
		}

		public static User AddUser(User user)
		{
			var existedUser = UserExist(user.Email);
			if (!existedUser)
			{
				Membership.CreateUser(user.Email, user.Password);

				Roles.AddUserToRole(user.Email, user.Role);

				var profile = ProfileCommon.GetProfile(user.Email);
				profile = user.Profile;
				profile.Save();

				return GetUser(user.Email);
			}

			return null;
		}

		public static void EditUser(User user)
		{
			var membershipUser = Membership.GetUser(user.Email);
			if (membershipUser != null)
			{
				// Edit user's normal information
				membershipUser.IsApproved = user.IsActive;
				Membership.UpdateUser(membershipUser);

				user.Profile.Save();

				// Only Administrator of this Module is allowed to change user roles
				if (IsUserInRole(AppVar.RoleAdministrators))
				{
					var oldRoles = Roles.GetRolesForUser(user.Email);
					if (oldRoles.Any())
					{
						Roles.RemoveUserFromRole(user.Email, oldRoles.FirstOrDefault());
						Roles.AddUserToRole(user.Email, user.Role);
					}
				}
			}
		}

		public static bool ChangePassword(string email, string password)
		{
			var membershipUser = Membership.GetUser(email);
			if (membershipUser != null)
			{
				var resetPassword = membershipUser.ResetPassword();
				membershipUser.ChangePassword(resetPassword, password);
				return true;
			}

			return false;
		}

		public static string ResetPassword(string email)
		{
			string ret = string.Empty;
			var membershipUser = Membership.GetUser(email);
			if (membershipUser != null)
			{
				ret = membershipUser.ResetPassword();
			}

			return ret;
		}

		public static Guid GetLoggedInUserId(string email)
		{
			return email.IsNullOrEmpty() ? (Guid)Membership.GetUser().ProviderUserKey : (Guid)Membership.GetUser(email).ProviderUserKey;
		}

		public static User GetUser(string email = "")
		{
			User user = null;
			var membershipUser = email.IsNullOrEmpty() ? Membership.GetUser() : Membership.GetUser(email);
			if (membershipUser != null)
			{
				user = GetUserFromMembershipUser(membershipUser);
			}

			return user;
		}

		public static List<User> GetUsers(string textFilter, bool? active = null, string role = "")
		{
			var membershipUsers = GetMembershipUsers(textFilter, active, role);
			return membershipUsers.Select(GetUserFromMembershipUser).ToList();
		}

		public static List<MembershipUser> GetMembershipUsers(string textFilter, bool? active = null, string role = "")
		{
			var users = Membership.GetAllUsers().Cast<MembershipUser>().Where(c => active == null || c.IsLockedOut != active).ToList();
			if (!string.IsNullOrEmpty(role))
			{
				users = users.Where(c => Roles.IsUserInRole(c.UserName, role)).ToList();
			}

			var userList = new List<MembershipUser>();
			if (!textFilter.IsNullOrEmpty())
			{
				textFilter = textFilter.ToLower();
				userList.AddRange(from membershipUser in users 
								  let right = membershipUser.UserName.ToLower().Contains(textFilter) 
								  where right 
								  select membershipUser);
			}
			else
			{
				userList.AddRange(users);
			}

			return userList.OrderBy(c => c.Email).ToList();
		}

		private static User GetUserFromMembershipUser(MembershipUser membershipUser)
		{
			var user = new User
			{
				IsActive = membershipUser.IsApproved,
				Email = membershipUser.UserName,
				Role = Roles.GetRolesForUser(membershipUser.UserName).FirstOrDefault(),
				Profile = ProfileCommon.GetProfile(membershipUser.UserName)
			};
			
			return user;
		}

		public static List<string> GetRoles()
		{
			return Roles.GetAllRoles().ToList();
		}
	}
}